package com.bsoft.gol.hcb.service.prescriptionCirculation;

import com.alibaba.fastjson.JSONObject;
import com.bsoft.gol.hcb.dao.prescriptionCirculation.*;
import com.bsoft.gol.hcb.serviceEnum.OutpatientTypeEnum;
import com.bsoft.gol.hcb.utils.CommonUtils;
import com.bsoft.gol.hcb.utils.DateUtils;
import com.bsoft.gol.hcb.utils.ResponseCode;
import com.bsoft.gol.mpi.model.Card;
import com.bsoft.gol.mpi.model.Person;
import com.bsoft.gol.mpi.provider.IMPIProvider;
import com.bsoft.gol.mpi.service.MPIException;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import ctd.controller.exception.ControllerException;
import ctd.net.rpc.Client;
import ctd.spring.boot.annotation.SsdevReference;
import ctd.spring.boot.annotation.SsdevService;
import hcn.base.BasePropertyConfig;
import hcn.base.Organization;
import hcn.base.drug.export.drugenum.DrugTypeEnum;
import hcn.enums.CardTypeEnum;
import hcn.ods.PayTrade;
import hcn.pay.event.PayTradeFinishEvent;
import hcn.pay.service.IPayTradeProcessor;
import hcn.protocol.base.hisPlateform.BaseHisPlateformClpInfoXmlRequest;
import hcn.protocol.base.hisPlateform.BaseHisPlateformPatientXmlRequest;
import hcn.protocol.base.hisPlateform.ProcessCodeEnums;
import hcn.protocol.enumcase.PayResultBusType;
import hcn.protocol.ods.diagnosis.CreateOrderNoResponseBean;
import hcn.protocol.ods.newdiagnosis.NewNotifyPayedRequestBean;
import hcn.protocol.ods.newdiagnosis.NewNotifyPayedResponseBean;
import hcn.protocol.ods.paymentXML.QueryPayedRequestBean;
import hcn.protocol.ods.paymentXML.QueryPayedResponseBean;
import hcn.protocol.ods.returnVisit.ConfirmDrugPayedRequestBean;
import hcn.util.BaseResponse;
import hcn.util.PayModeTransformUtil;
import mpi.security.cipher.sm.SM4Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import pcn.consultation.ConsultAsk;
import pcn.consultation.ExpressOrder;
import pcn.enums.ConsultTypeEnum;
import pcn.enums.FeeTypeEnum;
import pcn.prescribe.OdsExpressInfo;
import pcn.prescribe.OdsOrderToPrescription;
import pcn.prescribe.OdsPrescriptionOrder;
import pcn.prescriptionCirculation.OdsOrderExpenseRecord;
import pcn.prescriptionCirculation.OdsOrderPrescriptionInfo;
import pcn.vo.base.QueryDicContrastListVo;
import service.rpc.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 支付业务模块处理类
 */
@SsdevService("returnVisitPayTrade")
public class ReturnVisitPayTradeServiceImpl implements IPayTradeProcessor {
    private static final Logger LOGGER = LoggerFactory.getLogger(ReturnVisitPayTradeServiceImpl.class);

    @SsdevReference("gol-mpi.mpiProvider")
    private IMPIProvider hcnMpiProvider;
    @Autowired
    private OdsPrescriptionOrderDAO odsPrescriptionOrderDAO;
    @Autowired
    private OdsOrderToPrescriptionDAO odsOrderToPrescriptionDAO;
    @Autowired
    private PrescriptionInfoIntf prescriptionInfoIntf;
    @Autowired
    private ExpreeOrderDAO expreeOrderDAO;
    @Autowired
    private OrganizationInfoIntf organizationInfoService;
    @Autowired
    private ConsultAskServiceIntf consultAskServiceIntf;
    @Autowired
    private OdsExpressInfoDAO odsExpressInfoDAO;
    @Autowired
    private ServiceOpenIntf serviceOpenService;
    @Autowired
    private DisposalExpenseRecordServiceIntf disposalExpenseRecordServiceIntf;
    @Autowired
    private DiagnosisPayTradeIntf diagnosisPayTradeService;
    @Autowired
    private OdsOrderPrescriptionInfoDAO odsOrderPrescriptionInfoDAO;
    @Autowired
    private DicContrastService dicContrastService;
    @Autowired
    private OdsOrderExpenseRecordDAO odsOrderExpenseRecordDAO;


    @Override
    public Object preProcessTradeSuccess(PayTrade payTrade) throws ControllerException {
        LOGGER.info("========payTrade: {}", JSONObject.toJSON(payTrade));
        //支付回调
        Map<String, Object> map = new HashMap<>();
        String orderId = payTrade.getExternalTradeNo();
        OdsPrescriptionOrder odsPrescriptionOrder = odsPrescriptionOrderDAO.get(orderId);

        //若是有发票号，并且支付状态是已支付，表示已经支付确认过了,可以直接返回
        if(null != odsPrescriptionOrder && CommonUtils.isNotEmpty(odsPrescriptionOrder.getPaymentNumber())){
            return map;
        }

        NewNotifyPayedResponseBean notifyPayedResponseBean = null;
        //处方id集合
        List<String> prescribeIdList = new ArrayList<>();
        //检验检查申请单id集合
        List<String> expenseIdList = new ArrayList<>();

        NewNotifyPayedRequestBean request = new NewNotifyPayedRequestBean();

        //在线支付
        if ("1".equals(odsPrescriptionOrder.getPayWay())) {
            Organization organization = organizationInfoService.getOrgDetailByOrgId(odsPrescriptionOrder.getOrgId());

            //复诊配药只处理本次问诊的支付
            String consultId = "";
            List<OdsOrderToPrescription> odsOrderToPrescriptions = odsOrderToPrescriptionDAO.findOrderId(orderId);
            LOGGER.info("========odsOrderToPrescriptions: {}", JSONObject.toJSON(odsOrderToPrescriptions));
            //代煎费
            BigDecimal decoctingFee = new BigDecimal(0);
            //快递费
            BigDecimal expressFee = new BigDecimal(0);

            if (CommonUtils.isNotEmpty(odsOrderToPrescriptions)) {
                for (OdsOrderToPrescription odsOrderToPrescription : odsOrderToPrescriptions) {
                    if (FeeTypeEnum.XIYAO.getTitle().equals(odsOrderToPrescription.getFeeType()) || FeeTypeEnum.CHENGYAO.getTitle().equals(odsOrderToPrescription.getFeeType()) || FeeTypeEnum.CAOYAO.getTitle().equals(odsOrderToPrescription.getFeeType())) {
                        //获取处方id集合
                        prescribeIdList.add(odsOrderToPrescription.getFeeCode());//处方id
                        if (CommonUtils.isNotEmpty(odsOrderToPrescription.getConsultId())) {
                            consultId = odsOrderToPrescription.getConsultId();
                        }
                    } else if(!FeeTypeEnum.DJF.getTitle().equals(odsOrderToPrescription.getFeeType()) && !FeeTypeEnum.KDF.getTitle().equals(odsOrderToPrescription.getFeeType())){
                        //获取处方id集合
                        expenseIdList.add(odsOrderToPrescription.getFeeCode());//处方id
                        consultId = odsOrderToPrescription.getConsultId();
                    }

                    //代煎费
                    if (FeeTypeEnum.DJF.getTitle().equals(odsOrderToPrescription.getFeeType())) {
                        decoctingFee = new BigDecimal(odsOrderToPrescription.getTotalFee());
                    }

                    //快递费
                    if (FeeTypeEnum.KDF.getTitle().equals(odsOrderToPrescription.getFeeType())) {
                        expressFee = new BigDecimal(odsOrderToPrescription.getTotalFee());
                    }

                    //就诊序号赋值
                    if(CommonUtils.isNotEmpty(odsOrderToPrescription.getConsultId())){
                        //门诊缴费类型的直接取值，其他问诊类型的从问诊记录取
                        if(ConsultTypeEnum.CLINIC.getTitle().equals(odsOrderToPrescription.getConsultType())){
                            request.setVisitId(odsOrderToPrescription.getConsultId());
                        }else {
                            ConsultAsk consultAsk = consultAskServiceIntf.getConsultAskByConsultId(odsOrderToPrescription.getConsultId());
                            if(null != consultAsk){
                                request.setVisitId(consultAsk.getVisitNo());
                            }
                        }
                    }
                }
            }

            //"013705" text="复诊处方数据对接方式(0:json 1:xml),默认:0"
            BasePropertyConfig propertyCode = null;
            try {
                propertyCode = serviceOpenService.getBasePropertyConfig("013705", organization.getOrgId());
            } catch (Exception e) {
                LOGGER.error("查询系统参数失败：" + e.getMessage());
            }

            if (null != propertyCode && "1".equals(propertyCode.getPropertyData())) {
                try {
                    if (null != organization) {
                        Set<Card> cards = hcnMpiProvider.getCards(odsPrescriptionOrder.getMpiId());
                        String patientId = null;
                        if(CommonUtils.isNotEmpty(cards)){
                            List<Card> collect = cards.stream().filter(card -> card.getSource().equals(organization.getOrgId()) && CommonUtils.isNotEmpty(card.getPatientCode())).collect(Collectors.toList());
                            if(CommonUtils.isNotEmpty(collect)){
                                patientId = collect.get(0).getPatientCode();
                            }
                        }
                        if(null == patientId){
                            throw new ControllerException("该居民未绑定医院" + organization.getFullName() + "档案标识");
                        }
                        request.setPatientId(patientId);
                    }
                    request.setOrgId(organization.getOrgId());
                    //设置处方费用单据
                    setConfirmDrugPayedXmlRequest(request, consultId, payTrade, odsPrescriptionOrder);
                    //设置检验、检查费用单据
                    setConfirmExpenseXmlRequest(request, expenseIdList,odsPrescriptionOrder);

                    //设置抵用券
                    if(CommonUtils.isNotEmpty(odsPrescriptionOrder.getVoucherId())){
                        String[] voucherIds = odsPrescriptionOrder.getVoucherId().split("\\,");
                        if(CommonUtils.isNotEmpty(voucherIds)){
                            List<String> voucherIdList = new ArrayList<>();
                            for (String voucherId : voucherIds) {
                                voucherIdList.add(voucherId);
                            }
                            request.setVoucherIdList(voucherIdList);
                        }
                    }


                    if (CommonUtils.isNotEmpty(consultId)) {
                        ConsultAsk consultAsk = consultAskServiceIntf.getConsultAsksByConsultId(consultId);
                        if (consultAsk != null) {
                            //设置业务闭环
                            setRequest(consultAsk, request);
                        }
                    }
                    BigDecimal payAmount = new BigDecimal(payTrade.getTotalFee()).subtract(decoctingFee).subtract(expressFee);
                    BigDecimal totalFee = new BigDecimal(payTrade.getTotalFee()).subtract(decoctingFee).subtract(expressFee);
                    //TODO 确认结算的时候减去代煎费和快递费
                    request.setPayAmount(payAmount.setScale(2, RoundingMode.HALF_UP).doubleValue());
                    request.setTotalFee(totalFee.setScale(2, RoundingMode.HALF_UP).doubleValue());

                    request.setMedicalTechnologyOrgCode(organization.getMedicalTechnologyOrgCode());

                    //标准字典转化为his字典
                    Map<String,String> baseDicMap = new HashMap<>();
                    List<QueryDicContrastListVo> queryDicContrastListVos = dicContrastService.queryDicContrastList("fee_type", organization.getOrgId());
                    if(CommonUtils.isNotEmpty(queryDicContrastListVos)){
                        for (QueryDicContrastListVo queryDicContrastListVo : queryDicContrastListVos) {
                            baseDicMap.put(queryDicContrastListVo.getBaseItemCode(),queryDicContrastListVo.getHisItemCode());
                        }
                    }
                    for (NewNotifyPayedRequestBean.NotifyPayedRequestFeeRecordBean notifyPayedRequestFeeRecordBean : request.getFeeRecords()) {
                        if(baseDicMap.keySet().contains(notifyPayedRequestFeeRecordBean.getFeeTypeCode())){
                            notifyPayedRequestFeeRecordBean.setFeeTypeCode(baseDicMap.get(notifyPayedRequestFeeRecordBean.getFeeTypeCode()));
                        }
                    }
                    QueryPayedRequestBean queryPayedRequestBean = new QueryPayedRequestBean();
                    queryPayedRequestBean.setVisitOrganization(organization.getLocalOrgId());
                    queryPayedRequestBean.setBusType(PayResultBusType.CLINIC_PAY.getTypeCode());
                    queryPayedRequestBean.setBusTypeName(PayResultBusType.CLINIC_PAY.getTypeCodeName());
                    queryPayedRequestBean.setOutOrderNumber(payTrade.getOutOrderNumber());

                    QueryPayedResponseBean queryPayedResponseBean  = (QueryPayedResponseBean) Client.rpcInvoke("hcnInterface.diagnosisPayTradeService", "queryPayed", queryPayedRequestBean);

                    BaseResponse<NewNotifyPayedResponseBean> confirmDrugPayed = null;

                    if(null != queryPayedResponseBean && "1".equals(queryPayedResponseBean.getPayStatus())){
                        confirmDrugPayed = new BaseResponse<>();
                        NewNotifyPayedResponseBean newNotifyPayedResponseBean = new NewNotifyPayedResponseBean();
                        newNotifyPayedResponseBean.setAgtOrderNumber(queryPayedResponseBean.getAgtOrderNumber());
                        newNotifyPayedResponseBean.setResultId(queryPayedResponseBean.getPaymentNumber());
                        newNotifyPayedResponseBean.setInvoiceNumber(queryPayedResponseBean.getInvoiceCode());
                        newNotifyPayedResponseBean.setPaymentBudgetNumber(queryPayedResponseBean.getPaymentBudgetNumber());
                        newNotifyPayedResponseBean.setFeeRecords(Lists.newArrayList());
                        confirmDrugPayed.setCode(ResponseCode.SUCCESS);
                        confirmDrugPayed.setData(newNotifyPayedResponseBean);
                    }else {
                        LOGGER.info("========request: {}", JSONObject.toJSON(request));
                        LOGGER.info("========organization: {}", JSONObject.toJSON(organization));
                        confirmDrugPayed = diagnosisPayTradeService.notifyPayedXML(request, organization.getLocalOrgId());
                        LOGGER.info("========confirmDrugPayed: {}", JSONObject.toJSON(confirmDrugPayed));
                    }
                    if (null != confirmDrugPayed && null != confirmDrugPayed.getData()) {
                        notifyPayedResponseBean = confirmDrugPayed.getData();
                        //处理交易详情
                        dealPayedResponse(payTrade, notifyPayedResponseBean, prescribeIdList, expenseIdList);
                    }
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                    throw new ControllerException("his交易处理失败,"+throwable.getMessage());
                }
            }
        }
        map.put("prescribeIdList",prescribeIdList);
        map.put("expenseIdList",expenseIdList);
        map.put("notifyPayedResponseBean",notifyPayedResponseBean);
        LOGGER.info("========map: {}", JSONObject.toJSON(map));
        return map;
    }

    /**
     * @description: HIS支付成功后的业务处理
     * @author: chenJij@bsoft.com.cn
     * @date: 2023/2/6 10:48
     * @param: payTrade
     * @param: response
     * @return: void
     */
    public void dealPayedResponse(PayTrade payTrade, NewNotifyPayedResponseBean notifyPayedResponseBean, List<String> prescribeIdList, List<String> expenseIdList) throws ControllerException {
        String orderId = payTrade.getExternalTradeNo();
        OdsPrescriptionOrder odsPrescriptionOrder = odsPrescriptionOrderDAO.get(orderId);

        if (null != notifyPayedResponseBean) {
            odsPrescriptionOrder.setInvoiceNumber(notifyPayedResponseBean.getInvoiceNumber());
            odsPrescriptionOrder.setPaymentNumber(notifyPayedResponseBean.getResultId());
        }

        odsPrescriptionOrder.setPayStatus("1");
        odsPrescriptionOrder.setPayType(payTrade.getPayType());
        odsPrescriptionOrder.setAgtOrderNumber(payTrade.getPayServerTradeNo());
        odsPrescriptionOrder.setOrderStatus("1");
        odsPrescriptionOrder.setTradeNo(payTrade.getTradeNo());
        odsPrescriptionOrder.setPayTime(payTrade.getTradeTime());
        odsPrescriptionOrder.setPayFee(payTrade.getTotalFee());
        odsPrescriptionOrderDAO.update(odsPrescriptionOrder);

        odsPrescriptionOrderDAO.update(odsPrescriptionOrder);

        //创建供货商发货订单
        ExpressOrder expressOrder = expreeOrderDAO.getByOrderId(orderId);
        if (null == expressOrder) {
            expressOrder = new ExpressOrder();
            expressOrder.setExpressId(UUID.randomUUID().toString());
            expressOrder.setOrderId(orderId);
            expressOrder.setCreateTime(new Date());
            expressOrder.setDeleteFlag("0");
            expressOrder.setDeliverFlag("0");
            expressOrder.setConfirmReceipt("0");
            expreeOrderDAO.save(expressOrder);
        }

        //修改处方支付状态
        if (CommonUtils.isNotEmpty(prescribeIdList)) {
            prescriptionInfoIntf.updatePrescriptionPayStatus(prescribeIdList);
        }
        //修改处置记录支付状态
        if (CommonUtils.isNotEmpty(expenseIdList)) {
            disposalExpenseRecordServiceIntf.updatePayStatus(expenseIdList);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void processTradeSuccess(final PayTrade payTrade, Object response) throws ControllerException {

    }

    @Override
    public void afterProcessTradeSuccess(PayTrade payTrade) throws ControllerException {

    }

    @Override
    public void processTradeFailed(PayTrade payTrade) throws ControllerException {

    }

    @Override
    public boolean canRefund(PayTrade payTrade) throws ControllerException {
        return true;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void processReRefundSuccess(PayTrade payTrade) throws ControllerException {

    }

    @Override
    @SuppressWarnings("unchecked")
    public void processReRefundFailed(PayTrade payTrade) throws ControllerException {

    }


    /**
     * 创建订单时的额外参数
     */
    @Override
    public Map<String, Object> createOrderExtraInfo(PayTrade payTrade, Map<String, Object> params) throws ControllerException {
        //支付统一改造
        LinkedHashMap jsonObject = (LinkedHashMap) params.get("body");//交易内容json字符串
        Object orgId = params.get("hospitalCode");
        Object invoiceNumber = null == jsonObject.get("invoiceNumber") ? "" : jsonObject.get("invoiceNumber");
        Object orderId = null == jsonObject.get("orderId") ? "" : jsonObject.get("orderId");
        Object notify = null == params.get("notify") ? "" : params.get("notify");
        Object paymentBudgetNumber = jsonObject.get("paymentBudgetNumber") == null ? "" : jsonObject.get("paymentBudgetNumber");
        Object selfPay = params.get("amt");
        Object payState = null == params.get("payState") ? "" : params.get("payState");
        Object patientId = null == jsonObject.get("patientCode") ? "" : jsonObject.get("patientCode");

        List<String> voucherIdList = null;
        if(null != params.get("voucherIdList")){
            voucherIdList = (List<String>) params.get("voucherIdList");
        }

        @SuppressWarnings("unchecked")
        List<Map<String, Object>> feeRecords = (List<Map<String, Object>>) jsonObject.get("feeRecords");
        if (feeRecords == null) {
            return new ImmutableMap.Builder<String, Object>().put("error_result", "feeRecords参数不允许为空").build();
        }

        OdsPrescriptionOrder odsPrescriptionOrder = odsPrescriptionOrderDAO.get(payTrade.getExternalTradeNo());
        if(null == odsPrescriptionOrder){
            throw new ControllerException("订单不存在");
        }

        Organization organization = organizationInfoService.getOrgDetailByOrgId(odsPrescriptionOrder.getOrgId());
        if(null == organization){
            throw new ControllerException("机构不存在");
        }

        Person person = null;
        try {
            person = hcnMpiProvider.getPerson(odsPrescriptionOrder.getMpiId());
        } catch (MPIException e) {
            e.printStackTrace();
            throw new ControllerException("订单所属用户信息获取失败");

        }

        //获取his商户订单号
        String outOrderNumber = "";
        //whis的商户订单号和预结算标识一致
        if(CommonUtils.isNotEmpty(paymentBudgetNumber)){
            outOrderNumber = (String) paymentBudgetNumber;
        }else {
            CreateOrderNoResponseBean orderNoResponseBean = diagnosisPayTradeService.createOrderNo(organization.getLocalOrgId()
                    , PayResultBusType.CLINIC_PAY.getTypeCode(), payTrade.getTotalFee(), payTrade.getPayType()
                    , person.getCertificate().getCertificateType(), SM4Utils.decryptData_ECB(person.getCertificate().getCertificateNo()));
            if(null != orderNoResponseBean){
                outOrderNumber = orderNoResponseBean.getOutOrderNumber();
            }
        }

        List<OdsOrderToPrescription> orderIdList = odsOrderToPrescriptionDAO.findOrderId((String) orderId);
        String consultId = "";
        if(CommonUtils.isNotEmpty(orderIdList)){
            for (OdsOrderToPrescription odsOrderToPrescription : orderIdList) {
                if(CommonUtils.isNotEmpty(odsOrderToPrescription.getConsultId())){
                    consultId = odsOrderToPrescription.getConsultId();
                    break;
                }
            }
        }

        ConsultAsk consultAsk = null;
        if(null != consultId){
            consultAsk = consultAskServiceIntf.getConsultAskByConsultId(consultId);
        }

        String personName = null;
        String mpiId = null;
        String idCardNo = null;
        String medicalCardNumber = null;
        String orgName = null;
        String deptId = null;
        String deptName = null;
        String phoneNo = null;

        if(null != consultAsk){
            personName = consultAsk.getPersonName();
            mpiId = consultAsk.getConsultMpiId();
            idCardNo = consultAsk.getPatientIdentityCardNumber();
            medicalCardNumber = consultAsk.getPatientMedicalCardNumber();
            orgName = consultAsk.getOrgName();
            deptId = consultAsk.getDeptId();
            deptName = consultAsk.getDeptName();
            phoneNo = consultAsk.getPhoneNo();
        }else {
            if (hcn.util.CommonUtils.isNotEmpty(payTrade.getMpiId())) {
                Card card = null;
                try {
                    card = hcnMpiProvider.getCard(payTrade.getMpiId(), payTrade.getOrgId(), CardTypeEnum.MEDICAL_CARD.getTitle());
                } catch (MPIException e) {
                    e.printStackTrace();
                }
                if (hcn.util.CommonUtils.isNotEmpty(card)) {
                    medicalCardNumber = com.security.cipher.sm.SM4Utils.decryptData_ECB(card.getCardNo());
                    payTrade.setUserCardNo(medicalCardNumber);
                }
                if (hcn.util.CommonUtils.isNotEmpty(person)) {
                    mpiId = person.getMpiId();
                    personName = person.getPersonName();
                    payTrade.setPersonName(personName);

                    phoneNo = com.security.cipher.sm.SM4Utils.decryptData_ECB(person.getPhoneNo());
                    payTrade.setPhoneNo(phoneNo);
                    if (null != person.getCertificate()) {
                        idCardNo = com.security.cipher.sm.SM4Utils.decryptData_ECB(person.getCertificate().getCertificateNo());
                        payTrade.setIdCardNo(idCardNo);
                    }
                }
            }
            orgName = organization.getFullName();
            payTrade.setOrgName(orgName);
        }

        ImmutableMap.Builder<String, Object> stringObjectBuilder = new ImmutableMap.Builder<>();
        stringObjectBuilder.put("orgId", orgId)
                .put("notify", notify)
                .put("orderId", orderId)
                .put("patientId", patientId)
                .put("payState", payState)
                .put("invoiceNumber", invoiceNumber)
                .put("paymentBudgetNumber", paymentBudgetNumber)
                .put("tradeDate", new Date())
                .put("selfPay", selfPay)
                .put("outOrderNumber", outOrderNumber)
                .put("feeRecords", feeRecords).put("personName", personName == null ? "" : personName)
                .put("mpiId", mpiId == null ? "" : mpiId)
                .put("idCardNo", idCardNo == null ? "" : idCardNo)
                .put("medicalCardNumber", medicalCardNumber == null ? "" : medicalCardNumber)
                .put("orgName", orgName == null ? "" : orgName)
                .put("deptId", deptId == null ? "" : deptId)
                .put("deptName", deptName == null ? "" : deptName)
                .put("phoneNo", phoneNo == null ? "" : phoneNo);

        if(null != voucherIdList){
            stringObjectBuilder.put("voucherIdList", voucherIdList);
        }

        return stringObjectBuilder.build();
    }


    /**
     * 支付交易完成后的通知实现。
     *
     * @throws Exception
     */
    @Override
    public void notify(final PayTradeFinishEvent event) throws ControllerException {
        //TODD:整个交易完成后的通知事件
    }


    /**
     * @description: 设置请求入参
     * @author: chenJij@bsoft.com.cn
     * @date: 2020/10/31 11:37
     * @param: request
     * @param: consultId
     * @param: payTrade
     * @param: odsPrescriptionOrder
     * @param: odsExpressInfo
     * @param: prescribeIdList
     * @return: void
     */
    public void setConfirmDrugPayedXmlRequest(NewNotifyPayedRequestBean request, String consultId, PayTrade payTrade,
                                              OdsPrescriptionOrder odsPrescriptionOrder) throws ControllerException {

        if (CommonUtils.isNotEmpty(payTrade.getExtraData())) {
            Map<String, Object> extraMap = (Map<String, Object>) JSONObject.parseObject(payTrade.getExtraData());

            String orgId = (String) extraMap.get("orgId");
            String notify = (String) extraMap.get("notify");
            String payState = (String) extraMap.get("orgId");
            String invoiceNumber = (String) extraMap.get("invoiceNumber");
            String paymentBudgetNumber = (String) extraMap.get("paymentBudgetNumber");
            String outOrderNumber = (String) extraMap.get("outOrderNumber");
            String tradeDate = (String) extraMap.get("tradeDate");
            String selfPay = String.valueOf(extraMap.get("selfPay"));

            request.setInvoiceNumber(invoiceNumber);
            request.setPayMode(PayModeTransformUtil.hcnPayModeToHis(payTrade.getPayType()));
            request.setPayState(payState);
            request.setAgtOrderNumber(payTrade.getPayServerTradeNo());
            request.setPayAmount(payTrade.getTotalFee());
            request.setOutOrderNumber(outOrderNumber);
            request.setPaymentBudgetNumber(paymentBudgetNumber);
            request.setPayTime(DateUtils.toString(payTrade.getTradeTime(), "yyyy-MM-dd HH:mm:ss"));

            //his处方列表
            List<NewNotifyPayedRequestBean.NotifyPayedRequestFeeRecordBean> feeRecords = request.getFeeRecords();

            //线上处方列表
            List<OdsOrderPrescriptionInfo> orderPrescriptionInfoList = odsOrderPrescriptionInfoDAO.findByOrderId(odsPrescriptionOrder.getOrderId());

            if (CommonUtils.isNotEmpty(orderPrescriptionInfoList)) {

                if (null == feeRecords) {
                    feeRecords = new ArrayList<>();
                }
                //his处方对象
                NewNotifyPayedRequestBean.NotifyPayedRequestFeeRecordBean feeRecord;

                for (OdsOrderPrescriptionInfo OdsOrderPrescriptionInfo : orderPrescriptionInfoList) {
                    feeRecord = new NewNotifyPayedRequestBean.NotifyPayedRequestFeeRecordBean();
                    feeRecord.setFeeNo(OdsOrderPrescriptionInfo.getPrescriptionId());

                    String feeType = "";
                    String feeTypeName = "";
                    if (DrugTypeEnum.XIYAO.getCode().equals(OdsOrderPrescriptionInfo.getPrescriptionType())) {
                        feeType = FeeTypeEnum.XIYAO.getTitle();
                        feeTypeName = FeeTypeEnum.XIYAO.getContext();
                    } else if (DrugTypeEnum.ZHONGYAO.getCode().equals(OdsOrderPrescriptionInfo.getPrescriptionType())) {
                        feeType = FeeTypeEnum.CHENGYAO.getTitle();
                        feeTypeName = FeeTypeEnum.CHENGYAO.getContext();
                    } else if (DrugTypeEnum.CAOYAO.getCode().equals(OdsOrderPrescriptionInfo.getPrescriptionType())) {
                        feeType = FeeTypeEnum.CAOYAO.getTitle();
                        feeTypeName = FeeTypeEnum.CAOYAO.getContext();
                    }

                    feeRecord.setFeeTypeCode(feeType);
                    feeRecord.setFeeTypeName(feeTypeName);
                    feeRecords.add(feeRecord);

                    //云支付才去调用闭环,诊间支付不调用闭环
                    if(OutpatientTypeEnum.ON_LINE.getCode().equals(odsPrescriptionOrder.getSource())){
                        setClpInfo(consultId, request, OdsOrderPrescriptionInfo.getPrescriptionId(),
                                ProcessCodeEnums.PRESCRIPTION_CHARGE.getProcessCode(), ProcessCodeEnums.PRESCRIPTION_CHARGE.getProcessName(),
                                ProcessCodeEnums.PRESCRIPTION_CHARGE.getInterfaceCode(), ProcessCodeEnums.PRESCRIPTION_CHARGE.getInterfaceName());
                    }
                }
                request.setFeeRecords(feeRecords);
            }
        }
    }

    /**
     * @description: 设置闭环
     * @author: chenJij@bsoft.com.cn
     * @date: 2021/4/1 14:33
     */
    public void setClpInfo(String consultId, NewNotifyPayedRequestBean request, String businessID, String processCode, String processName, String interfaceCode, String interfaceName) throws ControllerException {
        ConsultAsk consultAsk = consultAskServiceIntf.getConsultAsksByConsultId(consultId);
        List<BaseHisPlateformClpInfoXmlRequest> clpInfos = request.getClpInfos();
        if (null == clpInfos) {
            clpInfos = new ArrayList<>();
        }
        BaseHisPlateformClpInfoXmlRequest clpInfoXmlRequest = new BaseHisPlateformClpInfoXmlRequest();
        clpInfoXmlRequest.setBusinessID(businessID);
        clpInfoXmlRequest.setBusinessCircleID("");
        clpInfoXmlRequest.setBusinessCompsiteID("");
        clpInfoXmlRequest.setFlowCode(processCode);
        clpInfoXmlRequest.setFlowName(processName);
        clpInfoXmlRequest.setOperateTypeCode(interfaceCode);
        clpInfoXmlRequest.setOperateTypeName(interfaceName);
        clpInfoXmlRequest.setOperatorCode(consultAsk.getLocalDoctorId());
        clpInfoXmlRequest.setOperatorName(consultAsk.getDoctorName());
        clpInfoXmlRequest.setOperateDeptCode(consultAsk.getOutpatientDeptCode());
        clpInfoXmlRequest.setOperateDeptName(consultAsk.getDeptName());
        String dateTime = DateUtils.toString(new Date(), "yyyy-MM-dd HH:mm:ss")
                .replace("-", "").replace(":", "")
                .replace(" ", "T");
        clpInfoXmlRequest.setOperateDateTime(dateTime);
        clpInfoXmlRequest.setGroupId("");
        clpInfoXmlRequest.setGroupName("");
        clpInfoXmlRequest.setOperateComments("");

        clpInfos.add(clpInfoXmlRequest);
        request.setClpInfos(clpInfos);
    }

    /**
     * @description: 请求闭环
     * @author: chenJij@bsoft.com.cn
     * @date: 2021/3/15 2:45
     * @param: consultAsk
     * @param: request
     * @return: void
     */
    public void setRequest(ConsultAsk consultAsk, NewNotifyPayedRequestBean request) throws ControllerException {

        Organization organization = organizationInfoService.getOrgDetailByOrgId(consultAsk.getOrgId());
        BaseHisPlateformPatientXmlRequest patient = new BaseHisPlateformPatientXmlRequest();
        patient.setSourcePatientId(consultAsk.getPatientCode());
        patient.setSourceVisitId(consultAsk.getVisitNo());
        patient.setClinicId(consultAsk.getPatientMedicalCardNumber());
        patient.setHospizationId("");
        //本次档案的类别，结合档案号确保院内档案的唯一。
        //OV:门诊档案 IV:住院档案HV:体检档案 XV:其他档案
        //当为非患者闭环时可为空，如高值耗材闭环
        patient.setSourcePatientIdType("OV");
        patient.setAuthorOrganization(organization.getLocalOrgId());
        patient.setName(consultAsk.getPersonName());
        request.setPatient(patient);
    }

    /**
     * @description: 保存检验检查费用信息
     * @author: chenJij@bsoft.com.cn
     * @date: 2020/11/17 13:29
     * @param: request
     * @param: expenseIdList
     * @return: void
     */
    public void setConfirmExpenseXmlRequest(NewNotifyPayedRequestBean request, List<String> expenseIdList,OdsPrescriptionOrder odsPrescriptionOrder) throws ControllerException {
        //保存处置信息
        if (CommonUtils.isNotEmpty(expenseIdList)) {
            String consultId = "";
            //his处置列表
            List<NewNotifyPayedRequestBean.NotifyPayedRequestFeeRecordBean> feeRecords = request.getFeeRecords();
            if (null == feeRecords) {
                feeRecords = new ArrayList<>();
            }
            //his处置对象
            NewNotifyPayedRequestBean.NotifyPayedRequestFeeRecordBean feeRecord;


            //线上处置列表
            List<OdsOrderExpenseRecord> odsOrderExpenseRecords = odsOrderExpenseRecordDAO.findByOrderId(odsPrescriptionOrder.getOrderId());
            if (CommonUtils.isNotEmpty(odsOrderExpenseRecords)) {
                for (OdsOrderExpenseRecord odsOrderExpenseRecord : odsOrderExpenseRecords) {
                    feeRecord = new NewNotifyPayedRequestBean.NotifyPayedRequestFeeRecordBean();

                    if (CommonUtils.isEmpty(consultId)) {
                        consultId = odsOrderExpenseRecord.getConsultId();
                    }

                    //4:检验  5:检查
                    if (FeeTypeEnum.JIANYAN.getTitle().equals(odsOrderExpenseRecord.getBillCategoryCode())) {
                        feeRecord.setFeeTypeCode(FeeTypeEnum.JIANYAN.getTitle());
                        feeRecord.setFeeTypeName(FeeTypeEnum.JIANYAN.getContext());

                    } else if (FeeTypeEnum.JIANCHA.getTitle().equals(odsOrderExpenseRecord.getBillCategoryCode())) {
                        feeRecord.setFeeTypeCode(FeeTypeEnum.JIANCHA.getTitle());
                        feeRecord.setFeeTypeName(FeeTypeEnum.JIANCHA.getContext());
                    }

                    //云支付才去调用闭环,诊间支付不调用闭环
                    if(OutpatientTypeEnum.ON_LINE.getCode().equals(odsPrescriptionOrder.getSource())){
                        if(CommonUtils.isNotEmpty(consultId)){
                            //4:检验  5:检查
                            if (FeeTypeEnum.JIANYAN.getTitle().equals(odsOrderExpenseRecord.getBillCategoryCode())) {
                                setClpInfo(consultId, request, odsOrderExpenseRecord.getApplicationNo(),
                                        ProcessCodeEnums.LAB_OUTPATIENT_ORDER_PAY.getProcessCode(), ProcessCodeEnums.LAB_OUTPATIENT_ORDER_PAY.getProcessName(),
                                        ProcessCodeEnums.LAB_OUTPATIENT_ORDER_PAY.getInterfaceCode(), ProcessCodeEnums.LAB_OUTPATIENT_ORDER_PAY.getInterfaceName());
                            } else if (FeeTypeEnum.JIANCHA.getTitle().equals(odsOrderExpenseRecord.getBillCategoryCode())) {
                                setClpInfo(consultId, request, odsOrderExpenseRecord.getApplicationNo(),
                                        ProcessCodeEnums.CHECK_OUTPATIENT_ORDER_PAY.getProcessCode(), ProcessCodeEnums.CHECK_OUTPATIENT_ORDER_PAY.getProcessName(),
                                        ProcessCodeEnums.CHECK_OUTPATIENT_ORDER_PAY.getInterfaceCode(), ProcessCodeEnums.CHECK_OUTPATIENT_ORDER_PAY.getInterfaceName());
                            }
                        }
                    }


                    feeRecord.setFeeNo(odsOrderExpenseRecord.getExpenseIdSource());

                    feeRecords.add(feeRecord);
                }
            }

            request.setFeeRecords(feeRecords);
        }
    }


    /**
     * @description: 设置请求入参
     * @author: chenJij@bsoft.com.cn
     * @date: 2020/10/31 11:37
     * @param: request
     * @param: consultId
     * @param: payTrade
     * @param: odsPrescriptionOrder
     * @param: odsExpressInfo
     * @param: prescribeIdList
     * @return: void
     */
    public void setConfirmDrugPayedRequest(ConfirmDrugPayedRequestBean request, String consultId, PayTrade payTrade,
                                           OdsPrescriptionOrder odsPrescriptionOrder, OdsExpressInfo odsExpressInfo, List<String> prescribeIdList) throws ControllerException {

//        ConsultAsk consultAsk = null;
//        if (CommonUtils.isNotEmpty(consultId)) {
//            consultAsk = consultAskServiceIntf.getConsultAsksByConsultId(consultId);
//            request.setPatientId(consultAsk.getPatientCode());
//            request.setEmergencyNumber(consultAsk.getVisitNo());
//            request.setAdmNumber(consultAsk.getVisitNo());
//        }
//
//        if (CommonUtils.isNotEmpty(payTrade.getExtraData())) {
//            Map<String, Object> extraMap = (Map<String, Object>) JSONObject.parseObject(payTrade.getExtraData());
//
//            String orgId = (String) extraMap.get("orgId");
//            String notify = (String) extraMap.get("notify");
//            String patientId = (String) extraMap.get("patientId");
//            String payState = (String) extraMap.get("orgId");
//            String invoiceNumber = (String) extraMap.get("invoiceNumber");
//            String paymentBudgetNumber = (String) extraMap.get("paymentBudgetNumber");
//            String tradeDate = (String) extraMap.get("tradeDate");
//            String selfPay = String.valueOf(extraMap.get("selfPay"));
//
//            request.setInvoiceNumber(invoiceNumber);
//            request.setPayMode(PayModeTransformUtil.hcnPayModeToHis(payTrade.getPayType()));
//            request.setPayState(payState);
//            request.setAgtOrderNumber(payTrade.getPayServerTradeNo());
//            request.setPayAmount(payTrade.getTotalFee());
//            request.setOutOrderNumber(payTrade.getOutOrderNumber());
//            request.setPaymentBudgetNumber(paymentBudgetNumber);
//            request.setPayTime(DateUtils.toString(payTrade.getTradeTime(), "yyyy-MM-dd HH:mm:ss"));
//            request.setPayWay(odsPrescriptionOrder.getPayWay());
//            request.setTakeWay(odsExpressInfo.getTakeWay());
//            request.setFreightCollectFlag(odsExpressInfo.getFreightCollectFlag());
//            request.setReciverProvince(odsExpressInfo.getReciverProvince());
//            request.setReciverCity(odsExpressInfo.getReciverCity());
//            request.setReciverDistrict(odsExpressInfo.getReciverDistrict());
//            request.setReciverStreet(odsExpressInfo.getReciverStreet());
//            request.setAddress(odsExpressInfo.getAddress());
//            request.setReciverName(odsExpressInfo.getReciverName());
//            request.setReciverPhone(odsExpressInfo.getTelephone());
//            request.setOnlineEmergencyNumber(consultId);
//            request.setDoctorId(consultAsk.getLocalDoctorId());
//            request.setDoctorName(consultAsk.getDoctorName());
//            request.setOnlineEmergencyNumber(consultId);
//            request.setStoreCode(odsExpressInfo.getStoreCode());
//
//            //保存病历信息
//            OdsVisitMedical visitMedical = odsVisitMedicalDAO.getOdsVisitMedicalByConsultId(consultAsk.getConsultId());
//            if (null != visitMedical) {
//                ConfirmDrugPayedRequestBean.MedicalRecordInformation medicalRecordInformation = new ConfirmDrugPayedRequestBean.MedicalRecordInformation();
//                medicalRecordInformation.setHandlingOpinions(visitMedical.getHandlingOpinions());
//                medicalRecordInformation.setMainComplaint(visitMedical.getMainComplaint());
//                medicalRecordInformation.setMedicalHistory(visitMedical.getMedicalHistory());
//                medicalRecordInformation.setPastHistory(visitMedical.getPastHistory());
//                medicalRecordInformation.setPatientName(consultAsk.getPersonName());
//                medicalRecordInformation.setPhysicalExamination(visitMedical.getPhysicalExamination());
//                medicalRecordInformation.setSupplementaryExamination(visitMedical.getSupplementaryExamination());
//                request.setMedicalRecordInformation(medicalRecordInformation);
//            }
//
//            //保存诊断信息
//            List<OdsDiagnosis> diagnosisList = diagnosisInfoIntf.queryOdsDiagnosisListByConsultId(consultAsk.getConsultId());
//            if (CommonUtils.isNotEmpty(diagnosisList)) {
//                List<ConfirmDrugPayedRequestBean.DiagnosticInformationList> diagnosticInformationList = new ArrayList<>();
//                ConfirmDrugPayedRequestBean.DiagnosticInformationList diagnosticInformation;
//                for (OdsDiagnosis odsDiagnosis : diagnosisList) {
//                    diagnosticInformation = new ConfirmDrugPayedRequestBean.DiagnosticInformationList();
//                    diagnosticInformation.setDiagnosisTime(DateUtils.toStringForYYYYMMddHHmmss(odsDiagnosis.getDiagnosisTime()));
//                    diagnosticInformation.setDiagnosticCode(odsDiagnosis.getDiseasesCode());
//                    diagnosticInformation.setDiagnosticId(odsDiagnosis.getDiagnosisId());
//                    diagnosticInformation.setDiagnosticName(odsDiagnosis.getDiseasesName());
//                    diagnosticInformation.setDiagnosticType(odsDiagnosis.getDiagnosisType());
//                    diagnosticInformation.setGroupNumber("1");
//                    diagnosticInformation.setMainDiagnosisSign(odsDiagnosis.getMainFlag());
//                    diagnosticInformation.setSortNumber("1");
//                    diagnosticInformation.setTcmSyndromeCode(odsDiagnosis.getTcmSyndromeCode());
//                    diagnosticInformation.setTcmSyndromeName(odsDiagnosis.getTcmSyndromeName());
//
//                    diagnosticInformationList.add(diagnosticInformation);
//                }
//                request.setDiagnosticInformationList(diagnosticInformationList);
//            }
//
//            //保存处方信息
//            if (CommonUtils.isNotEmpty(prescribeIdList)) {
//                //his处方列表
//                List<ConfirmDrugPayedRequestBean.PrescriptionInformationListBean> prescriptionInformationList = new ArrayList<>();
//                //his处方对象
//                ConfirmDrugPayedRequestBean.PrescriptionInformationListBean prescriptionInformationListBean;
//                //his处方药品列表
//                List<ConfirmDrugPayedRequestBean.PrescriptionInformationListBean.DrugListBean> drugList = null;
//                //his处方药品
//                ConfirmDrugPayedRequestBean.PrescriptionInformationListBean.DrugListBean drugListBean = null;
//
//                //线上处方列表
//                List<OdsPrescriptionInfo> odsPrescriptionInfoList = prescriptionInfoIntf.queryByFeeNoList(prescribeIdList);
//                if (CommonUtils.isNotEmpty(odsPrescriptionInfoList)) {
//                    for (OdsPrescriptionInfo odsPrescriptionInfo : odsPrescriptionInfoList) {
//                        prescriptionInformationListBean = new ConfirmDrugPayedRequestBean.PrescriptionInformationListBean();
//                        prescriptionInformationListBean.setDrugType(Integer.valueOf(odsPrescriptionInfo.getPrescriptionType()));
//                        prescriptionInformationListBean.setPrescriptionInfoId(odsPrescriptionInfo.getPrescriptionInfoId());
//                        prescriptionInformationListBean.setDoctorId(consultAsk.getLocalDoctorId());
//                        prescriptionInformationListBean.setDoctorName(consultAsk.getDoctorName());
//                        prescriptionInformationListBean.setAuditDoctorId(odsPrescriptionInfo.getAuditLocalDoctorId());
//                        prescriptionInformationListBean.setAuditor(odsPrescriptionInfo.getAuditor());
//                        prescriptionInformationListBean.setAuditMind(odsPrescriptionInfo.getAuditMind());
//                        prescriptionInformationListBean.setAuditTime(DateUtils.toString(odsPrescriptionInfo.getAuditTime(), "yyyy-MM-dd HH:mm:ss"));
//                        prescriptionInformationListBean.setAuditStatus(odsPrescriptionInfo.getAuditStatus());
//                        prescriptionInformationListBean.setCreateTime(DateUtils.toString(odsPrescriptionInfo.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
//                        prescriptionInformationListBean.setNumberOfPackets(odsPrescriptionInfo.getNumberOfPackets());
//                        prescriptionInformationListBean.setBoilSign(odsPrescriptionInfo.getBoilSign() == null ? 0 : odsPrescriptionInfo.getBoilSign());
//
//                        List<OdsPrescriptionDrug> odsPrescriptionDrugList = odsPrescriptionDrugDAO.findByInfoId(odsPrescriptionInfo.getPrescriptionInfoId());
//
//                        if (CommonUtils.isNotEmpty(odsPrescriptionDrugList)) {
//                            int i = 0;
//                            drugList = new ArrayList<>();
//                            for (OdsPrescriptionDrug odsPrescriptionDrug : odsPrescriptionDrugList) {
//                                drugListBean = new ConfirmDrugPayedRequestBean.PrescriptionInformationListBean.DrugListBean();
//                                drugListBean.setDrugId(odsPrescriptionDrug.getOrgDrugId());
//                                drugListBean.setDrugName(odsPrescriptionDrug.getOrgDrugName());
//                                drugListBean.setFactoryId(odsPrescriptionDrug.getOrgFactoryId());
//                                drugListBean.setFactoryName(odsPrescriptionDrug.getOrgFactoryName());
//                                drugListBean.setSpecification(odsPrescriptionDrug.getSpecification());
//                                drugListBean.setDose(odsPrescriptionDrug.getDose() == null ? 0 : odsPrescriptionDrug.getDose().doubleValue());
//                                drugListBean.setDoseUnit(odsPrescriptionDrug.getDoseUnit());
//                                drugListBean.setQuantity(odsPrescriptionDrug.getQuantity() == null ? 0 : odsPrescriptionDrug.getQuantity().doubleValue());
//                                drugListBean.setPrice(odsPrescriptionDrug.getPrice() == null ? 0 : odsPrescriptionDrug.getPrice().doubleValue());
//                                drugListBean.setTakeDays(odsPrescriptionDrug.getTakeDays());
//                                drugListBean.setFrequencyCode(odsPrescriptionDrug.getFrequencyCode());
//                                drugListBean.setFactoryName(odsPrescriptionDrug.getFrequencyName());
//                                drugListBean.setUsageCode(odsPrescriptionDrug.getUsageCode());
//                                drugListBean.setUsageName(odsPrescriptionDrug.getUsageName());
//                                drugListBean.setDecoctionCode(odsPrescriptionDrug.getDecoctionCode());
//                                drugListBean.setDecoctionName(odsPrescriptionDrug.getDecoctionName());
//                                drugListBean.setPackUnit(odsPrescriptionDrug.getPackUnit());
//                                drugListBean.setGroupNumber(1);
//                                drugListBean.setSortNumber(i++);
//                                drugListBean.setRemark(odsPrescriptionDrug.getRemark());
//
//                                drugList.add(drugListBean);
//                            }
//
//                            prescriptionInformationListBean.setDrugList(drugList);
//                        }
//                        prescriptionInformationList.add(prescriptionInformationListBean);
//                    }
//                }
//                request.setPrescriptionInformationList(prescriptionInformationList);
//            }
//        }
    }
}
